import sensor
import display
import time
import image
from pyb import UART

sensor.reset()  # Initialize the camera sensor.
sensor.set_pixformat(sensor.RGB565)  # or sensor.GRAYSCALE
sensor.set_framesize(sensor.QQVGA2)  # Special 128x160 framesize for LCD Shield.

UART_HEADER = 0xCC
UART_FOOTER = 0xDD
uart = UART(3, 115200)
uart.init(115200, bits=8, parity=None, stop=1)
# Initialize the lcd screen.
lcd = display.SPIDisplay()

# 获取LCD的分辨率
lcd_width = lcd.width()
lcd_height = lcd.height()

# 创建一个空白图像用于显示文本，指定像素格式为RGB565
text_img = image.Image(lcd_width, lcd_height, sensor.RGB565)

# 设置字体大小(缩放比例)
title_scale = 2  # 标题字体缩放
content_scale = 2  # 内容字体缩放

# 初始显示一个启动信息
text_img.clear()
text_img.draw_string(10, 10, "QR Code", color=(255, 255, 255), scale=title_scale)
text_img.draw_string(10, 40, "Scanner Ready", color=(255, 255, 255), scale=content_scale)
lcd.write(text_img)


def send_data_bytes(data_bytes):
    """
    发送字节数据到STM32
    参数: data_bytes - 字节串或可迭代的字节序列
    """
    uart.writechar(UART_HEADER)
    for byte in data_bytes:
        uart.writechar(byte)  # 逐个字节发送
    uart.writechar(UART_FOOTER)


def send_string(text):
    """
    发送文本字符串
    """
    send_data_bytes(text.encode('utf-8'))


# 初始状态：等待指令
start = True

while True:
    # 检查UART是否有数据（移到主循环内）
    if uart.any():
        data = uart.read(1)
        if data == b'\x01':
            start = True
            print("Ready to scan QR code")

    if start:
        img = sensor.snapshot()  # 拍摄一张图像
        qr_codes = img.find_qrcodes()  # 查找二维码

        # 如果找到了二维码
        if qr_codes:
            for qr in qr_codes:
                # 清空文本图像
                text_img.clear()

                # 在文本图像上绘制二维码标题
                text_img.draw_string(10, 10, "QR Content:", color=(255, 255, 255), scale=title_scale)

                # 获取二维码内容并保存副本
                content = qr.payload()

                # 发送二维码内容到STM32（只发送一次）
                send_string(content)
                print("QR content:", content)

                # 分行显示较长的内容
                # 根据字体大小和屏幕宽度计算每行最大字符数
                chars_per_line = int(lcd_width / (8 * content_scale))  # 估算值，可能需要调整

                display_content = content  # 使用内容副本进行显示
                y_pos = 50  # 内容起始y坐标

                while display_content:
                    # 取出当前行文本
                    if len(display_content) <= chars_per_line:
                        line = display_content
                        display_content = ""
                    else:
                        line = display_content[:chars_per_line]
                        display_content = display_content[chars_per_line:]

                    # 绘制当前行
                    text_img.draw_string(10, y_pos, line, color=(255, 255, 255), scale=content_scale)
                    y_pos += int(20 * content_scale)  # 行间距也要根据缩放比例调整

                    # 如果超出屏幕，则停止
                    if y_pos >= lcd_height - 10:
                        break

                # 将文本图像显示到LCD上
                lcd.write(text_img)

                # 重置状态，等待下一个指令
                start = False
